﻿#include "GxImageOperator.h"
#include <QThread>
#include <QDebug>
#include <QMutexLocker>
#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlError>
#include <QDir>


GxImageOperator::GxImageOperator(QObject *resultObj, int index)
    : QObject()
    , m_pRevObj(resultObj)
    , m_iCurrentIndex(qMax(0, index))
    , m_uiTotalImages(0)
{
    m_pQueryModel = new QSqlQueryModel(this);
    //m_pQueryModel->setHeaderData(0, Qt::Horizontal, tr("Dir Name"));
}

GxImageOperator::~GxImageOperator()
{
    if (m_pQueryModel)
	{
		m_pQueryModel->deleteLater();
		m_pQueryModel = nullptr;
	}
    stop();
}


void GxImageOperator::work()
{
    if(!initDB())
    {
        return;
    }
    m_pQueryModel->setQuery("SELECT dir FROM tb_dirs");
    return;
}

void GxImageOperator::push(DBOperationInfo node)
{
    switch(node.type)
    {
        case OT_ADDDIR:
        {
            addDir(node);
            updateRowCount();
            updateModel();
        }
        break;

        case OT_REMOVEDIR:
        {
            removedir(node);
            updateRowCount();
            updateModel();
        }
        break;

        case OT_NEXT:
        {
            next();
        }
        break;

        case OT_PREVIOUS:
        {
            previous();
        }
        break;

        default:
            break;
    }
}

void GxImageOperator::stop()
{
    QSqlDatabase::database().close(); //关闭数据库
    emit done();
}

void GxImageOperator::updateModel()
{
    QString queryStr = m_pQueryModel->query().executedQuery();
	m_pQueryModel->clear();
	m_pQueryModel->query().clear();
	m_pQueryModel->setQuery(queryStr);

    qDebug() << "update model, row in total" << m_pQueryModel->rowCount();

}

QSqlQueryModel* GxImageOperator::getModel()
{
    return m_pQueryModel;
}

quint32 GxImageOperator::count() const
{
    return m_uiTotalImages;
}

int GxImageOperator::index() const
{
    return m_iCurrentIndex;
}

bool GxImageOperator::initDB()
{
    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");  
    db.setHostName("localhost");  //数据库主机名   
    db.setDatabaseName("imagelist");   //数据库名   
    //打开数据库连接  调用 open() 方法打开数据库物理连接。在打开连接之前，连接不可用
    if (!db.open())
    {
        qDebug() << "Sqlite open fail" << endl;
        return false;
    }
    //创建表
    createTable();
    updateRowCount();
    //next(); //初始化后直接获取下一张
    return true;
}

void GxImageOperator::createTable()
{
    
    QString strCmd = QString("CREATE TABLE IF NOT EXISTS tb_images (\
                  id INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,\
                  dir VARCHAR(255) NOT NULL,\
                  image VARCHAR(255) NOT NULL,\
                  valid INTEGER NOT NULL);"\
                  );

    QSqlQuery query;
    query.exec(strCmd);

    strCmd = QString("CREATE TABLE IF NOT EXISTS tb_dirs (\
                  id INTEGER  NOT NULL PRIMARY KEY AUTOINCREMENT,\
                  dir VARCHAR(255) NOT NULL,\
                  recursive INTEGER NOT NULL,\
                  valid INTEGER NOT NULL);"\
                  );
    query.exec(strCmd);
}

void GxImageOperator::addDir(const DBOperationInfo& node)
{
    QString strDirPath = node.strDir;
    QFileInfo dirInfo(strDirPath);
    if(!dirInfo.isDir())    
        return;

    //检查是否存在相同的目录，或者包含这个目录且有递归的目录
    QString strCmd = QString("SELECT * FROM tb_dirs WHERE dir = :dir");
    QSqlQuery query;
    query.prepare(strCmd);
    query.bindValue(":dir", strDirPath);
    if(!query.exec())
    {
        return;
    }
    if(query.next())
    {
        //存在同名目录，不处理
        qDebug() << "已包含此目录";
        return;
    }

    //插入一条目录信息
    QString strInsertDir = QString("INSERT INTO tb_dirs VALUES(NULL, :dir, 0, 1)");
    query.prepare(strInsertDir);
    query.bindValue(":dir", strDirPath);
    if(!query.exec())
    {
        qDebug() << "插入目录列表失败" << strDirPath;
        return;
    }

    //遍历目录查找图片
    
    QStringList listPictureFileNames = getPictureFromDir(dirInfo);
    foreach(QString filename, listPictureFileNames)
    {
        //入库
        QString strInsertImage = QString("INSERT INTO tb_images VALUES(NULL, :dir, :image, 1)");
        query.prepare(strInsertImage);
        query.bindValue(":dir", strDirPath);
        query.bindValue(":image", filename);
        query.exec();
    }
}

void GxImageOperator::removedir(const DBOperationInfo& node)
{
    QString strDirPath = node.strDir;
    QFileInfo dirInfo(strDirPath);
    if(!dirInfo.isDir())    
        return;

    //移除目录列表中的项
    QString strRemoveFromDirs = QString("DELETE FROM tb_dirs WHERE dir = :dir");
    QSqlQuery query;
    query.prepare(strRemoveFromDirs);
    query.bindValue(":dir", strDirPath);
    query.exec();

    //移除图片列表中的项
    QString strRemoveFromImages = QString("DELETE FROM tb_images WHERE dir = :dir");
    query.prepare(strRemoveFromImages);
    query.bindValue(":dir", strDirPath);
    query.exec();
}

void GxImageOperator::next()
{
    QString strImage;
    if(!getCurrentImage(strImage))
    {
        return;
    }
    if(strImage.isEmpty())
    {
        //STOP TIMER
        //QMetaObject::invokeMethod(m_pRevObj, "stop", Qt::QueuedConnection, Q_ARG(bool, true));
        qDebug() << "因为没有找到图片";
        return;
    }
    QMetaObject::invokeMethod(m_pRevObj, "setCurrentImage", Qt::QueuedConnection, Q_ARG(QString, strImage));
    m_iCurrentIndex++;
}


void GxImageOperator::previous()
{
    QString strImage;
    if(!getCurrentImage(strImage))
    {

    }
    if(strImage.isEmpty())
    {
        //STOP TIMER
        //QMetaObject::invokeMethod(m_pRevObj, "stop", Qt::QueuedConnection, Q_ARG(bool, true));
        qDebug() << "因为没有找到图片";
        return;
    }
    QMetaObject::invokeMethod(m_pRevObj, "setCurrentImage", Qt::QueuedConnection, Q_ARG(QString, strImage));
    m_iCurrentIndex--;
    if(m_iCurrentIndex < 0)
    {
        m_iCurrentIndex = m_uiTotalImages - 1;
    }
}

bool GxImageOperator::getCurrentImage(QString& strImage)
{
    strImage.clear();

    QString strCmd = QString("SELECT * FROM tb_images LIMIT 1 OFFSET :offset;");
    QSqlQuery query;
    query.prepare(strCmd);
    query.bindValue(":offset", m_iCurrentIndex);
    if(!query.exec())
    {
        return false;
    }
    if(!query.next())
    {
        m_iCurrentIndex = 0;
        query.bindValue(":offset", m_iCurrentIndex);
        if(!query.exec() || !query.next())
        {
            qDebug() << "找不到图片";
            return true;
        }
    }
    QString strPath = query.value(1).toString();
    QString strFileName = query.value(2).toString();
    bool bIsValid = query.value(3).toBool();
    if(!strPath.endsWith("/"))
    {
        strPath.append("/");
    }
    strImage = strPath + strFileName;
    return true;
}

QStringList GxImageOperator::getPictureFromDir(const QFileInfo &dirInfo, bool recursive)
{
    QStringList listResult;
    if(!dirInfo.isDir())
        return listResult;

    QDir dir;
    dir.setPath(dirInfo.filePath());
    QFileInfoList filelist = dir.entryInfoList(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot);
    //图片后缀名列表
    static QStringList listPictureSuffix = {"png", "jpg", "jpeg", "bmp"};

    
    foreach(QFileInfo fileInfo, filelist)
    {
        QString strSuffix = fileInfo.suffix().toLower();
        if(listPictureSuffix.contains(strSuffix))
        {
            listResult << fileInfo.fileName();
        }
    }

    return listResult;
}

void GxImageOperator::updateRowCount()
{
    QString strCmd = QString("SELECT COUNT(*) FROM tb_images;");
    QSqlQuery query;
    query.prepare(strCmd);
    if(!query.exec())
    {
        qDebug() << "get count error";
        return;
    }
    if(query.next())
    {
        quint32 uiPrevious = m_uiTotalImages;
        m_uiTotalImages = query.value(0).toUInt();
        qDebug() << "image count " << m_uiTotalImages;
        //如果之前是0且现在大于0,则开始，否则stop
        if(uiPrevious <= 0 && m_uiTotalImages > 0)
        {
            QMetaObject::invokeMethod(m_pRevObj, "start", Qt::QueuedConnection);
            qDebug() << "开始幻灯片";
        }
        if(uiPrevious > 0 && m_uiTotalImages <= 0)
        {
            m_iCurrentIndex = 0;
            QMetaObject::invokeMethod(m_pRevObj, "stop", Qt::QueuedConnection, Q_ARG(bool, true));
            qDebug() << "停止幻灯片";
        }
    }
    else
    {
        qDebug() << "get count error";
    }
}